package bgapi

import (
	"bgs/db"
	sqlc "bgs/db/sqlc"
	userService "bgs/service/user"
	"bgs/util"
	"bytes"
	"context"
	"encoding/json"
	"fmt"

	"github.com/nsqio/go-nsq"
	"go.uber.org/zap"
)

var (
	lastStoreFollowMessage *StoreFollowMessage = nil
)

// StoreFollowMessage StoreFollow message struct
type StoreFollowMessage struct {
	TS   int64 `json:"ts"`
	Data struct {
		// 用户
		UserID int64 `json:"user_id"`
		// 关注的品牌
		FollowedStoreID int64 `json:"followed_store_id"`
		// 关注时间
		Followed int64 `json:"followed"`
	} `json:"data"`
}

// StoreFollowHandler StoreFollow message handler
type StoreFollowHandler struct {
	dao         *db.PgDao
	slog        *zap.SugaredLogger
	userService *userService.UserServiceImp
}

// NewStoreFollowHandler create a new handler for StoreFollow
func NewStoreFollowHandler(
	pgdao *db.PgDao,
	slog *zap.SugaredLogger,
	userService *userService.UserServiceImp,
) *StoreFollowHandler {
	return &StoreFollowHandler{
		dao:         pgdao,
		slog:        slog.With("module", "StoreFollowHandler"),
		userService: userService,
	}
}

// HandleMessage implements the Handler interface.
func (h *StoreFollowHandler) HandleMessage(m *nsq.Message) error {
	if len(m.Body) == 0 {
		// Returning nil will automatically send a FIN command to NSQ to mark the message as processed.
		return nil
	}

	h.slog.Infof("StoreFollowMessage=>%s", string(m.Body))

	v := &StoreFollowMessage{}
	if decodeErr := json.NewDecoder(bytes.NewReader(m.Body)).Decode(v); decodeErr != nil {
		return fmt.Errorf("无法解析信息[StoreFollowMessage]: %v", decodeErr)
	}
	if lastStoreFollowMessage != nil && lastStoreFollowMessage.TS >= v.TS {
		h.slog.Infof("过时的消息: lastStoreFollowMessage.TS:%v,v.TS:%v", lastStoreFollowMessage.TS, v.TS)
		return nil
	}

	userID := v.Data.UserID
	ctx := context.Background()

	err := h.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		_, err = h.dao.Q.UpsertStoreFollow(ctx, sqlc.UpsertStoreFollowParams{
			UserID:          userID,
			FollowedStoreID: v.Data.FollowedStoreID,
			Followed:        util.MsToGoTime(v.Data.Followed),
		})
		if err != nil {
			return err
		}
		h.slog.Infof("a StoreFollowHandler-插入/更新门店关注关系 ok")

		err = h.userService.UpdateUserStatSinceFollowStore(ctx, q, userID)
		if err != nil {
			return err
		}
		h.slog.Infof("b StoreFollowHandler-用户关注门店统计到(UserStat) ok")
		return
	})

	if err != nil {
		return err
	}
	lastStoreFollowMessage = v
	// Returning a non-nil error will automatically send a REQ command to NSQ to re-queue the message.
	return nil
}
